import http from 'wechat-http'

// 请求基准地址
// 注意：URL屁股后面没有 /，所以，在真正发请求的位置 URL 前面要加个 /
http.baseURL = 'https://live-api.itheima.net'

http.intercept.request = (config) => {
  console.log(config, 'config')

  const { token } = getApp().globalData

  if (token) {
    config.header = Object.assign({ Authorization: token }, config.header)
  }

  // 一定要返回，类似于 axios 的请求拦截器
  return config
}

http.intercept.response = async (res) => {
  console.log(res, 'res111111')

  const { statusCode, config } = res

  // token 失效了
  if (statusCode === 401) {
    // 有可能本次请求就是刷新token，
    // 如果是，说明refresh_token 也失效了，就不用再刷，再刷死循环了

    // 或者 如果没有 refreshToken，就不用去 刷新 token
    const { refreshToken } = getApp().globalData

    if (config.url.endsWith('/refreshToken') || !refreshToken) {
      // 说明是刷新token 401 的
      // 只能去登录了
      // 登录之后，我们还要跳回来，所以要获取当前页面的url

      const lastPageURL = [...getCurrentPages()].pop().route
      wx.redirectTo({
        url: '/pages/login/index?redirectURL=' + lastPageURL,
      })
      // 这个返回值会作用响应数据
      // return wx.utils.toast('请先登录一下吧！')

      // 当前错误的异步调用流程：访问个人详情页面 ==> onLoad ==> 获取用户信息 ==> token失效了 ==> 响应拦截器 ==> 401 ==> 刷新token ==> 响应拦截器 ==> 401 ==> 弹出“请先登录一下吧！”提示 ==> return undefined ==> 所以刷新token请求得到的响应数据就是undefined ==> 下一个.then就会进入成功的逻辑(value=undefined) ==> 存token ==> 重新发上一次失败的请求

      // 解决思路：如果刷新token都401了，那么就不能让后面的 .then链 进入成功了，要进入失败的逻辑，怎么让后续的链式调用失败呢？ 上一个 .then 返回一个失败的 Promise 实例 或者 直接 throw 错误对象

      // 正确的异步调用流程：访问个人详情页面 ==> onLoad ==> 获取用户信息 ==> token失效了 ==> 响应拦截器 ==> 401 ==> 刷新token ==> 响应拦截器 ==> 401 ==> 弹出“请先登录一下吧！”提示 ==> 不能让后续的链式调用继续成功，要进入错误回调 ==> return Promise.reject(错误对象) 或者 throw 错误对象 ==> 刷新token的请求就会失败 ==> await 刷新token请求 下面的代码就不会执行 ==> 没有try ... catch 抓异常 ==> 接着往外抛异常 ==> 获取用户信息 就会失败 ==> await 获取用户信息 下面的代码也不会执行了 ==> 如果也没有 try...catch ==> 接着往外抛异常 ==> 抛到控制台上了

      wx.utils.toast('请先登录一下吧！')
      return Promise.reject(new Error('refreshToken已失效'))
    }

    // 如果能走到这里，说明是 请求的token 失效了
    // 去刷新token
    // try {
    const { data } = await http({
      method: 'POST',
      url: '/refreshToken',
      header: {
        Authorization: refreshToken,
      },
    })
    // } catch (err) {
    //   return wx.utils.toast('错误')
    //   // return undefined  后面还是会成功  ==> 页面发获取用户信息的请求就会走成功的逻辑
    // }

    // 更新到 Storage 中
    getApp().globalMethods.setToken(data.token, data.refreshToken)

    // token 刷新完毕

    // 再次重新发起请求

    // config 就是上一次请求的请求配置
    // 但是 里面包含了 上一次 失效的 token
    // 再次请求时，需要先干掉它或者替换它

    delete config.header.Authorization

    // 因为 http 的返回值类型是 Promise
    // 所以 根据 Promise 的链式调用规则，后面的 .then 逻辑 会等待前面返回的Promise成功后 再执行
    // return http(config)

    // const res = await http(config)
    // return res

    // 这行代码和上面注释的两行代码是等价的
    return await http(config)
  }

  // 注意：一定要 return，否则页面上调用请求后，拿不到响应数据
  return res.data
}

// 挂到全局对象wx上
wx.http = http

// 统一的按需导出 出口
export { http }

// 默认导出
export default http
